﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data.Entity.Core;
using System.Data.Entity.Core.Objects;
using System.Data.Entity;

namespace Chinaer.Dao.EF
{
    public abstract class Repository<T>
        where T : class
    {
        private static ChinaerContext _instance = null;

        public ChinaerContext ChinaerDbContext
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new ChinaerContext();
                }
                return _instance;
            }

        }
        public bool EnableTrack
        {
            get;
            set;
        }

        protected void WriteLog(string content)
        {
            WriteLog("DAOError", "DAO", content);
        }
        protected void WriteLog(string remark, string content)
        {
            WriteLog("DAOError", remark, content);
        }
        protected void WriteLog(string fileName, string remark, string content)
        {
            Chinaer.Core.Helper.LogHelper.Instance.WriteLog(fileName, remark, content);
        }

        public virtual IList<T> Query(string sql, int pageIndex, out int recordCount, int pageSize, params SqlParameter[] sqlParams)
        {

            var list = EnableTrack ? this.ChinaerDbContext.Set<T>().SqlQuery(sql, sqlParams)
                : this.ChinaerDbContext.Set<T>().SqlQuery(sql, sqlParams).AsNoTracking();
            recordCount = list.Count();
            return list.Skip(pageIndex * pageSize).Take(pageSize).ToList();
        }
        /// <summary>
        /// 必须在子类实例化 重写
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T GetByID(string id)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 必须在子类实例化 重写
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual bool Exists(string id)
        {
            throw new NotImplementedException();
        }

        public virtual bool Add(T entity)
        {
            if (entity == null)
            {
                throw new Exception("EF添加出现错误,实体为NULL");
            }

            using (ChinaerContext context = ChinaerContext.GetNewInstance())
            {
                try
                {
                    context.Entry<T>(entity).State = System.Data.Entity.EntityState.Added;
                    return context.SaveChanges() == 1 ? true : false;
                }
                catch (System.Data.Entity.Infrastructure.DbUpdateConcurrencyException dbEx)
                {
                    if (context.Entry<T>(entity).State == System.Data.Entity.EntityState.Modified)
                    {
                        context.Entry<T>(entity).State = EntityState.Added;
                        return context.SaveChanges() == 1;
                    }
                }
                catch (System.Data.Entity.Validation.DbEntityValidationException ex)
                {
                    if (ex.EntityValidationErrors != null && ex.EntityValidationErrors.Count() > 0)
                    {
                        foreach (System.Data.Entity.Validation.DbEntityValidationResult item in ex.EntityValidationErrors)
                        {
                            if (item != null && item.ValidationErrors.Count > 0)
                            {
                                foreach (System.Data.Entity.Validation.DbValidationError error in item.ValidationErrors)
                                {
                                    Chinaer.Core.Helper.LogHelper.Instance.WriteLog("EntityError", "Entity framework", string.Format("errorMessage:{0}  propertyName:{1}", error.ErrorMessage, error.PropertyName));
                                }
                            }
                        }

                    }

                }
            }
            return false;

        }

        public virtual bool Update(T entity)
        {
            if (entity == null)
            {
                throw new Exception("EF更新错误,实体为NULL");
            }
            using (ChinaerContext context = ChinaerContext.GetNewInstance())
            {
                try
                {
                    context.Entry<T>(entity).State = System.Data.Entity.EntityState.Modified;
                    return context.SaveChanges() == 1;
                }
                catch (System.Data.Entity.Validation.DbEntityValidationException ex)
                {
                    if (ex.EntityValidationErrors.Count() > 0)
                    {
                        System.Data.Entity.Validation.DbEntityValidationResult validateResult = ex.EntityValidationErrors.FirstOrDefault();
                        if (validateResult != null)
                        {
                            System.Data.Entity.Validation.DbValidationError error = validateResult.ValidationErrors.FirstOrDefault();
                            if (error != null)
                            {
                                WriteLog("EntityFramework_UpdateEntityError", "EntityFramework", error.ErrorMessage);
                            }
                        }
                    }
                }
                catch (System.Data.Entity.Infrastructure.DbUpdateConcurrencyException dbEx)
                {
                    var entry = dbEx.Entries.Single();
                    var currentValues = entry.CurrentValues;
                    var databaseValues = entry.GetDatabaseValues();

                    // Choose an initial set of resolved values. In this case we
                    // make the default be the values currently in the database.
                    var resolvedValues = databaseValues.Clone();

                    // Have the user choose what the resolved values should be


                    // Update the original values with the database values and
                    // the current values with whatever the user choose.
                    entry.OriginalValues.SetValues(databaseValues);
                    entry.CurrentValues.SetValues(resolvedValues);
                    if (context.Entry<T>(entity).State == System.Data.Entity.EntityState.Modified)
                    {
                        ///重新从数据库中获取数据

                        context.Entry<T>(entity).State = System.Data.Entity.EntityState.Modified;
                        return context.SaveChanges() == 1;
                    }
                }
                return false;
            }
        }

        public virtual bool Delete(T entity)
        {
            if (entity == null)
            {
                throw new Exception("EF删除错误,实体为NULL");
            }
            using (ChinaerContext context = ChinaerContext.GetNewInstance())
            {
                context.Entry<T>(entity).State = System.Data.Entity.EntityState.Deleted;
                //context.Set<T>().Remove(entity);
                int result = context.SaveChanges();
                return result == 1;
            }
        }
        /// <summary>
        /// 必须在子类重写
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual bool Delete(string id)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 必须在子类重写
        /// </summary>
        /// <param name="listID"></param>
        /// <returns></returns>
        public virtual int DeleteByIDs(IList<string> listID)
        {
            throw new NotImplementedException();
        }
    }
}
